package one.stand.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.CommonRequest;
import com.aliyuncs.CommonResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import io.netty.buffer.ByteBufUtil;
import one.stand.code.RedisCode;
import one.stand.config.ComponentConfig;
import one.stand.config.WxPcLoginConfig;
import one.stand.config.WxUrlConfig;
import one.stand.entity.TokenEntity;
import one.stand.enums.*;
import one.stand.exception.LoginException;
import one.stand.model.*;
import one.stand.request.*;
import one.stand.response.BusinessCardResponse;
import one.stand.response.GlobalConfigurationResponse;
import one.stand.response.LoginResponse;
import one.stand.service.CommontService;
import one.stand.service.CompanyAccontService;
import one.stand.service.HomeService;
import one.stand.service.checkparam.HomeServiceCheckParam;
import one.stand.util.HttpUtil;
import one.stand.util.OssUtil;
import one.stand.util.RandomUtil;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.encoders.Base64;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.*;
import java.security.spec.InvalidParameterSpecException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author Administrator
 */
@Service
public class HomeServiceImpl extends PublicBaseService implements HomeService {

    @Autowired
    private WxUrlConfig urlConfig;
    @Autowired
    private OssUtil ossUtil;
    @Autowired
    private WxUrlConfig wxUrlConfig;
    @Autowired
    private WxPcLoginConfig wxPcLoginConfig;
    @Autowired
    private CompanyAccontService companyAccontService;
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultModel<TokenEntity> getLoginInfo(String loginKey) {
        TokenEntity tokenModel = new TokenEntity();
        tokenModel.setRoleId(324332324);
        return ResultModel.success(redisUtil.get(RedisCode.getUserLoginToken(loginKey)));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultModel<LoginResponse> loginByWeixin(WxLoginRequest request) {
        log.info("参数接收：{}",JSON.toJSONString(request));
        if (HomeServiceCheckParam.wxLogin(request)) {
            return ResultModel.fail(ResultEnum.PARAM_CHECK);
        }
        try {
            LoginEnum loginEnum = EnumUtil.getByIntegerTypeCode(LoginEnum.class, "getCode", request.getLoginProgramName());
            if (null == loginEnum) {
                return ResultModel.checkParamFail();
            }
            CompanyModel c=companyMapper.select(new CompanyModel(){{
                setCompanyKey(request.getCompanyKey());
            }});
            if(c==null){
                return ResultModel.fail("账号信息错误，请联系管理员");
            }
            if(c.getCompanyState().equals(CompanyStateEnums.PROHIBIT.getState())){
                return ResultModel.fail("小程序已被禁用请联系管理员");
            }

            CompanyAccountModel companyAccountModel = companyAccontService.selectByUserIdCopy(new CompanyAccountRequest() {{
                setCompanyKey(request.getCompanyKey());
                setAccountType(loginEnum.getAccountType());
            }});
            if (companyAccountModel == null) {
                return ResultModel.fail("未购买服务，请联系客服");
            }
            if(!companyAccountModel.getState().equals(1)){
                return ResultModel.fail("您的小程序还未通过验证");
            }
            JSONObject jsonObject = getSessionKeyAndOpenId(request.getCode(),companyAccountModel);
            log.info("微信登陆返回内容：" + jsonObject);
            String openId = jsonObject.getString("openid");
            String sessionKey = jsonObject.getString("session_key");
            String errCode = jsonObject.getString("errcode");
            if (!StringUtils.isEmpty(errCode)) {
                return ResultModel.fail("登陆Code已过期");
            }
            if (StringUtils.isEmpty(openId)) {
                return ResultModel.fail("获取失败");
            }
            String unionId = jsonObject.getString("unionid");
            JSONObject userInfo = null;
            if (StringUtils.isEmpty(unionId)) {
                userInfo = getUserInfo(request.getEncrypteData(), sessionKey, request.getIv());
                log.info("用户session信息:" + userInfo);
                unionId = userInfo.getString("unionId");
            }
//            JsCode2sessionResponse response  =  LoginApi.jscode2session(commontService.getComponentToken(),companyAccountModel.getAppId(),componentConfig.getAppid(),request.getCode());
//            log.info("微信登陆返回内容：" + response.toString());
//            String openId = response.getOpenid();
//            String sessionKey = response.getSessionKey();
//            Integer errCode = response.getErrcode();
//            if (!errCode.equals(0)) {
//                return ResultModel.fail(response.getErrmsg());
//            }
//            JSONObject userInfo = getUserInfo(request.getEncrypteData(), sessionKey, request.getIv());
//            log.info("用户session信息:" + userInfo);
//            String unionId = userInfo.getString("unionId");
            if(StringUtils.isEmpty(unionId)){
                return ResultModel.fail("请绑定开平台");
            }

            UserModel inModel = new UserModel();
            inModel.setUnionid(unionId);
            inModel = userMapper.select(inModel);
            if (inModel == null) {
                if (null == userInfo) {
                    userInfo = getUserInfo(request.getEncrypteData(), sessionKey, request.getIv());
                }
                log.info("微信用户信息：" + userInfo);
                inModel = new UserModel();
                inModel.setAvatarUrl(userInfo.getString("avatarUrl"));
                inModel.setGender(userInfo.getInteger("gender"));
                inModel.setCity(userInfo.getString("city"));
                inModel.setProvince(userInfo.getString("province"));
                inModel.setCountry(userInfo.getString("country"));
                inModel.setAvatarUrl(userInfo.getString("avatarUrl"));
                inModel.setNickeName(new String(java.util.Base64.getEncoder().encode(userInfo.getString("nickName").getBytes()), "UTF-8"));
                inModel.setCreateTime(currentDate());
                inModel.setUnionid(unionId);
                inModel.setEnterpriseId(companyAccountModel.getCompanyId());
                if (request.getLoginProgramName().equals(LoginEnum.CRM.getCode())) {
                    inModel.setCrmOpenId(openId);
                }
                if (request.getLoginProgramName().equals(LoginEnum.USER.getCode())) {
                    inModel.setOpenId(openId);
                }
                userMapper.insertSelective(inModel);
            }else{
                //crm登录 用户绑定
                if (request.getLoginProgramName().equals(LoginEnum.CRM.getCode())) {
                    if (StringUtils.isEmpty(inModel.getCrmOpenId())) {
                        inModel.setCrmOpenId(openId);
                    }
                }
                //用户端登录 用户绑定
                if (request.getLoginProgramName().equals(LoginEnum.USER.getCode())) {
                    if (StringUtils.isEmpty(inModel.getOpenId())) {
                        inModel.setOpenId(openId);
                    }
                }
                if(userInfo != null && userInfo.getString("nickName") != null) {
                    inModel.setNickeName(new String(java.util.Base64.getEncoder().encode(userInfo.getString("nickName").getBytes()), "UTF-8"));
                }
                userMapper.updateByPrimaryKeySelective(inModel);
            }
            try {
                LoginResponse loginResponse=init(inModel,request.getCompanyKey(),sessionKey,request.getLoginProgramName(),null);
                return ResultModel.success(loginResponse);
            } catch (LoginException e) {
                return ResultModel.fail(e.getMessage());
            }
        } catch (Exception e) {
            log.error("登陆异常:", e);
            return ResultModel.fail("登录失败");
        }
    }

    @Override
    public ResultModel<Boolean> loginVerification(String token) {
        TokenEntity tokenEntity = redisUtil.get(RedisCode.getUserLoginToken(token));
        if (tokenEntity == null) {
            return ResultModel.success(false);
        }
        return ResultModel.success(true);
    }

    @Override
    @Cacheable(value = "login-service", key = "#root.targetClass.toString()+'.'+#root.methodName+':'+#userId", unless = "#result.data==null")
    public ResultModel<BusinessCardResponse> userInfo(Long userId) {
        BusinessCardResponse response = new BusinessCardResponse();
        BusinessCardModel model = businessCardMapper.select(new BusinessCardModel() {{
            setUserId(userId.intValue());
            setState(1);
        }});
        BeanUtils.copyProperties(model, response);
        return ResultModel.success(response);
    }

    @Override
    public ResultModel<String> getPhone(GetWxPhoneRequest request) {
        try {
            if (StringUtils.isEmpty(request.getPhoneData()) || StringUtils.isEmpty(request.getPhoneIv())) {
                return ResultModel.checkParamFail();
            }
            TokenEntity tokenEntity = redisUtil.get(RedisCode.getUserLoginToken(request.getToken()));
            JSONObject sessionJson = getUserInfo(request.getPhoneData(), tokenEntity.getSessionKey(), request.getPhoneIv());
            log.info("解析手机号：{}", sessionJson);
            UserModel userModel = userMapper.selectByPrimaryKey(request.getId().intValue());
            userModel.setPhone(sessionJson.getString("purePhoneNumber"));
            userMapper.updateByPrimaryKeySelective(userModel);
            return ResultModel.success(userModel.getPhone());
        } catch (Exception e) {
            log.info("获取用户手机号失败。。。");
            return ResultModel.fail();
        }
    }

    @Override
    public ResultModel getPcLoginImg(String companyKey) {
        try {
            if(StringUtils.isEmpty(companyKey)){
                return ResultModel.checkParamFail();
            }
            CompanyAccountModel companyAccountModel = companyAccontService.selectByUserIdCopy(new CompanyAccountRequest() {{
                setCompanyKey(companyKey);
                setAccountType(LoginEnum.CRM_PC.getAccountType());
            }});
            if(null==companyAccountModel){
                return ResultModel.account();
            }
            StringBuffer url = new StringBuffer(wxUrlConfig.getLoginImgUrl()).append("?");
            url.append("appid=").append(companyAccountModel.getAppId()).append("&");
            url.append("redirect_uri=").append(URLEncoder.encode(companyAccountModel.getRedirectUri(), "UTF-8")).append("&");
            url.append("response_type=").append(wxPcLoginConfig.getResponseType()).append("&");
            url.append("scope=").append("snsapi_login").append("&");
            url.append("state=").append(companyKey);
            log.info("二維碼地址{}", url.toString());
            return ResultModel.success(url.toString());
        } catch (Exception e) {
            e.printStackTrace();
            return ResultModel.error();
        }
    }

    @Override
    public ResultModel pcLoginCallBack(String code, String state) {
        log.info("收到pc登陆回调" + code + "----" + state);
        if (StringUtils.isEmpty(code)) {
            return ResultModel.fail("code is null");
        }
        CompanyAccountModel companyAccountModel = companyAccontService.selectByUserIdCopy(new CompanyAccountRequest() {{
            setCompanyKey(state);
            setAccountType(LoginEnum.CRM_PC.getAccountType());
        }});
        if(!companyAccountModel.getState().equals(1)){
            return ResultModel.fail("您的小程序还未通过验证");
        }
        Map<String, String> param = new HashMap<>(4);
        param.put("code", code);
        param.put("appid", companyAccountModel.getAppId());
        param.put("secret", companyAccountModel.getAppSecret());
        param.put("grant_type", wxPcLoginConfig.getGrantType());
        String res = HttpUtil.sendPost(wxPcLoginConfig.getLoginOauth2Url(), param);
        log.info("获取到用户登陆信息：" + res);
        JSONObject jsonObject = JSONObject.parseObject(res);
        if(StringUtils.isEmpty(jsonObject.getString("unionid"))){
            return ResultModel.fail("登录code过期，请重新操作");
        }
        UserModel userModel = userMapper.select(new UserModel() {{
            setUnionid(jsonObject.getString("unionid"));
        }});
        if (null == userModel) {
            return ResultModel.fail("用户不存在");
        }
        if (StringUtils.isEmpty(userModel.getCrmOpenId())) {
            return ResultModel.fail("您还未注册使用小程序");
        }
        try {
            LoginResponse loginResponse=init(userModel,state,null,LoginEnum.CRM_PC.getCode(),null);
            return ResultModel.success(loginResponse);
        } catch (LoginException e) {
            return ResultModel.fail(e.getMessage());
        }
    }

    @Override
    public ResultModel<List<GlobalConfigurationResponse>> initial(GlobalConfigurationRequest request) {
        List<GlobalConfigurationModel> list = globalConfigurationMapper.selectList(new GlobalConfigurationModel() {{
            setGlobalProgramName(request.getGlobalProgramName());
            setGlobalType(request.getGlobalType());
        }});
        List<GlobalConfigurationResponse> responseList = new ArrayList<>();
        list.forEach(l -> {
            GlobalConfigurationResponse response = new GlobalConfigurationResponse();
            BeanUtils.copyProperties(l, response);
            responseList.add(response);
        });
        return ResultModel.success(responseList);
    }

    @Override
    public ResultModel<Boolean> batchDelToken(Long[] ids) {
        for (Long id : ids) {
            redisUtil.batchDel(RedisCode.getUserLoginToken("*_" + id));
        }
        return ResultModel.success(true);
    }

    @Autowired
    ComponentConfig componentConfig;

    @Autowired
    CommontService commontService;

    /**
     * 获取微信小程序的session_key和openid
     *
     * @param code 微信前端login()方法返回的code
     * @return jsonObject
     * @author hengyang4
     */
    public JSONObject getSessionKeyAndOpenId(String code,CompanyAccountModel companyAccountModel) {
        //微信登录的code值
        String wxCode = code;
        //读取属性文件
        //服务器端调用接口的url
        String requestUrl = urlConfig.getWxLogin();
        String appId = companyAccountModel.getAppId();
        String secret = companyAccountModel.getAppSecret();
        //封装需要的参数信息
        Map<String, String> requestUrlParam = new HashMap<>(4);
        //开发者设置中的appId
        requestUrlParam.put("appid", appId);
        //开发者设置中的appSecret
        requestUrlParam.put("secret", secret);
        //小程序调用wx.login返回的code
        requestUrlParam.put("js_code", wxCode);
        //默认参数
        requestUrlParam.put("grant_type", "authorization_code");
        JSONObject jsonObject = JSON.parseObject(HttpUtil.sendPost(requestUrl, requestUrlParam));
        return jsonObject;
    }


    /**
     * 解密用户敏感数据获取用户信息
     *
     * @param sessionKey    数据进行加密签名的密钥
     * @param encryptedData 包括敏感数据在内的完整用户信息的加密数据
     * @param iv            加密算法的初始向量
     * @return
     * @author zhy
     */
    public JSONObject getUserInfo(String encryptedData, String sessionKey, String iv) {
        String result = "";
        // 被加密的数据
        byte[] dataByte = Base64.decode(encryptedData);
        // 加密秘钥
        byte[] keyByte = Base64.decode(sessionKey);
        // 偏移量
        byte[] ivByte = Base64.decode(iv);
        try {
            // 如果密钥不足16位，那么就补足. 这个if 中的内容很重要
            int base = 16;
            if (keyByte.length % base != 0) {
                int groups = keyByte.length / base
                        + (keyByte.length % base != 0 ? 1 : 0);
                byte[] temp = new byte[groups * base];
                Arrays.fill(temp, (byte) 0);
                System.arraycopy(keyByte, 0, temp, 0, keyByte.length);
                keyByte = temp;
            }
            // 初始化
            Security.addProvider(new BouncyCastleProvider());
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");
            SecretKeySpec spec = new SecretKeySpec(keyByte, "AES");
            AlgorithmParameters parameters = AlgorithmParameters
                    .getInstance("AES");
            parameters.init(new IvParameterSpec(ivByte));
            // 初始化
            cipher.init(Cipher.DECRYPT_MODE, spec, parameters);
            byte[] resultByte = cipher.doFinal(dataByte);
            if (null != resultByte && resultByte.length > 0) {
                result = new String(resultByte, "UTF-8");
            }
        } catch (NoSuchAlgorithmException e) {
            log.error(e.getMessage(), e);
        } catch (NoSuchPaddingException e) {
            log.error(e.getMessage(), e);
        } catch (InvalidParameterSpecException e) {
            log.error(e.getMessage(), e);
        } catch (IllegalBlockSizeException e) {
            log.error(e.getMessage(), e);
        } catch (BadPaddingException e) {
            log.error(e.getMessage(), e);
        } catch (UnsupportedEncodingException e) {
            log.error(e.getMessage(), e);
        } catch (InvalidAlgorithmParameterException e) {
            log.error(e.getMessage(), e);
        } catch (NoSuchProviderException e) {
            log.error(e.getMessage(), e);
        } catch (java.security.InvalidKeyException e) {
            log.error(e.getMessage(), e);
        }
        return JSON.parseObject(result);
    }


    @Value("${sms.accountKeyId}")
    private String accountKeyId;
    @Value("${sms.accessKeySecret}")
    private String accessKeySecret;
    @Value("${sms.outId}")
    private String outId;
    @Value("${sms.signName}")
    private String signName;
    @Override
    public ResultModel<Boolean> sendSms(SendSmsCodeRequest request) {
        if(StringUtils.isEmpty(request.getPhone())||request.getPhone().length()!=11){
            return ResultModel.checkParamFail();
        }
        if(redisUtil.hasKey(RedisCode.getSmsLockKey(request.getPhone()))){
            return ResultModel.fail("操作频繁");
        }
        String smsCode=RandomUtil.generateNumberString(6);
        redisUtil.set(RedisCode.getSmsKey(request.getPhone(),request.getType()),smsCode,30,TimeUnit.MINUTES);
        redisUtil.set(RedisCode.getSmsLockKey(request.getPhone()),request.getIp(),60,TimeUnit.SECONDS);


        sendSmsCode(request,smsCode);

        return ResultModel.success(true);
    }
    @Async("asyncServiceExecutor")
    public void sendSmsCode(SendSmsCodeRequest request,String code){
        DefaultProfile profile=DefaultProfile.getProfile("default",accountKeyId,accessKeySecret);
        IAcsClient client=new DefaultAcsClient(profile);
        CommonRequest commonRequest=new CommonRequest();
        commonRequest.setMethod(MethodType.POST);
        commonRequest.setDomain("dysmsapi.aliyuncs.com");
        commonRequest.setVersion("2017-05-25");
        commonRequest.setAction("SendSms");
        SmsCodeEnums smsCodeEnums=EnumUtil.getByIntegerTypeCode(SmsCodeEnums.class,"getCode",request.getType()+"");
        commonRequest.putBodyParameter("PhoneNumbers",request.getPhone());
        commonRequest.putBodyParameter("TemplateCode",smsCodeEnums.getTemplateCode());
        commonRequest.putBodyParameter("TemplateParam","{code:"+code+"}");
        commonRequest.putBodyParameter("SignName",signName);
        try {
            CommonResponse response = client.getCommonResponse(commonRequest);
            log.info("短信发送结果：{}",response.getData());
        }catch (Exception e){
            log.error("短信发送异常：{}",e.getMessage());
        }
    }


    @Override
    public ResultModel<LoginResponse> crmPcLoginBySms(WxLoginRequest request) {
        if(StringUtils.isEmpty(request.getSmsCode())||StringUtils.isEmpty(request.getPhone())||request.getPhone().length()!=11||request.getCompanyId()==null){
            return ResultModel.checkParamFail();
        }
        String redisSmsCode=redisUtil.get(RedisCode.getSmsKey(request.getPhone(),SmsCodeEnums.login_sms.getCode()));
        log.info("删除用户验证码缓存");
        redisUtil.remove(RedisCode.getSmsKey(request.getPhone(),SmsCodeEnums.login_sms.getCode()));
        redisUtil.remove(RedisCode.getSmsLockKey(request.getPhone()));
        if(!redisSmsCode.equals(request.getSmsCode())){
            return ResultModel.fail("证码错误");
        }

        CompanyModel companyModel=companyMapper.selectByPrimaryKey(request.getCompanyId());
        if(null==companyModel){
            return ResultModel.fail("企业不存在");
        }
        UserModel userModel=userMapper.select(new UserModel(){{
            setCardPhone(request.getPhone());
            setCompanyKey(companyModel.getCompanyKey());
        }});
        if(null==userModel){
            return ResultModel.fail("用户不存在");
        }
        try {
            LoginResponse loginResponse=init(userModel,request.getCompanyKey(),null,LoginEnum.CRM_PC.getCode(),companyModel.getCompanyId());
            return ResultModel.success(loginResponse);
        } catch (LoginException e) {
            return ResultModel.fail(e.getMessage());
        }

    }


    @Override
    public ResultModel<List<CompanyModel>> getCompanyListByPhone(SendSmsCodeRequest request) {
        if(StringUtils.isEmpty(request.getPhone())||request.getPhone().length()!=11){
            return ResultModel.success();
        }
        List<CompanyModel> list=companyMapper.getCompanyByUserPhone(request.getPhone());
        return ResultModel.success(list);
    }

    private LoginResponse init(UserModel userModel, String companyKey, String accessToken, String loginProgramName, Integer companyId) throws LoginException {
        LoginResponse loginResponse = new LoginResponse();
        TokenEntity tokenModel = new TokenEntity();
        tokenModel.setId(userModel.getUserId());
        tokenModel.setToken(RandomUtil.generateString(10) + "_" + userModel.getUserId());
        tokenModel.setLogintime(currentDate());

        BusinessCardModel cardModel = businessCardMapper.select(new BusinessCardModel() {{
            setUserId(userModel.getUserId().intValue());
            setState(1);
            setCompanyId(companyId);
        }});
        if (LoginEnum.CRM_PC.getCode().equals(loginProgramName)&&cardModel == null) {
            throw  new LoginException("您还没有权限登录");
        }
        tokenModel.setSessionKey(accessToken);
        tokenModel.setCompanyKey(companyKey);
        tokenModel.setLoginProgramName(loginProgramName);
        tokenModel.setRoleId(0);
        tokenModel.setCId(0L);
        tokenModel.setMyCardId(0);
        if(null!=cardModel){
            if(userModel.getRoleId().equals(cardModel.getCompanyId())){
                tokenModel.setRoleId(userModel.getRoleId());
                // 更新到新的版本 多名片是通过名片中的roleid 设置权限
                if(!cardModel.getCompanyId().equals(cardModel.getRoleId())){
                    cardModel.setRoleId(cardModel.getCompanyId());
                    businessCardMapper.updateByPrimaryKeySelective(cardModel);
                    log.info("名片权限数据切换。。。");
                }
            }
            tokenModel.setCId(cardModel.getCompanyId().longValue());
            tokenModel.setMyCardId(cardModel.getCardId());
            loginResponse.setCompanyName(cardModel.getCompanyName());

        }
        log.info("登录缓存信息：{}",JSON.toJSONString(tokenModel));
        redisUtil.set(RedisCode.getUserLoginToken(tokenModel.getToken()), tokenModel, LOGIN_TIME_LONG, TimeUnit.SECONDS);
        loginResponse.setUserId(userModel.getUserId());
        loginResponse.setToken(tokenModel.getToken());
        loginResponse.setAvatarUrl(userModel.getAvatarUrl());
        loginResponse.setUserName(StringUtils.isEmpty(userModel.getNickeName()) ? "" : new String(java.util.Base64.getDecoder().decode(userModel.getNickeName())));
        loginResponse.setRoleId(userModel.getRoleId());
        loginResponse.setOssUrl(ossUtil.getOssUrl());
        loginResponse.setPhone(userModel.getPhone());
        if(null!=cardModel){
            loginResponse.setCardId(cardModel.getCardId());
        }else {
            loginResponse.setCardId(0);
        }
        if(cardModel!=null){
            loginResponse.setIsAgent(cardModel.getIsAgent());
        }
        return loginResponse;
    }


    public static void main(String[] args) {
        String code = "47455420687474703a2f2f62616964752e636f6d2f20485454502f312e310d0a557365722d4167656e743a204d6f7a696c6c612f342e302028636f6d70617469626c653b204d53494520382e303b2057696e646f7773204e5420362e313b2054726964656e742f342e30290d0a436f6e6e656374696f6e3a20636c6f73650d0a486f73743a2062616964752e636f6d0d0a50726f78792d436f6e6e656374696f6e3a204b6565702d416c6976650d0a4163636570742d456e636f64696e673a20677a69702c6465666c6174650d0a0d0a";
        byte[] bytes = ByteBufUtil.decodeHexDump(code);
        System.out.println(new String(bytes));
    }

}
